using System;
using System.Collections.Generic;
using System.Text;
using RapidHDL.Fabric;

namespace RapidHDL
{
    public class SNNMaster : FabricComponent 
    {
        int iPCWidth;
        int iConstWidth;
        int iIRWidth;

        public SNNMaster(Component poParentComponent, string psName, ClockComponent poClock, NodeVector pnvReset)
            : base(poParentComponent,psName,poClock,pnvReset)
        {            
        }

        MicroCoreBlock oMicroCore;
        //ProgramROMBlock oProgramROM;
        ProgramROMRAMBlock oProgram;

        public override void DefineFabric()
        {
            MicroCoreTable oTable = new SNNCore();
            string sROMProgramPath = "c:\\ROM.asm";
            string sRAMProgramPath = "c:\\SNN.rasm";
            
            ContainerBlock.CreateConstant("ZERO_BIT", 0, 1);
            ContainerBlock.CreateConstant("ONE_BIT", 1, 1);

            ContainerBlock.CreateExternalBusInput("EQI", 64);
            ContainerBlock.CreateExternalBusOutput("EQO", 42);

            ContainerBlock.CreateExternalBusInput("MEMQI", 42);
            ContainerBlock.CreateExternalBusOutput("MEMQO", 64);

            oMicroCore = ContainerBlock.CreateMicroCore("CORE", oTable);
            //oProgramROM = ContainerBlock.CreateProgramROM("PROG", oTable, sProgram);
            oProgram = ContainerBlock.CreateProgramROMRAM("PROG", oTable, sROMProgramPath,sRAMProgramPath, 100, 400, 32);

            
            iPCWidth = oProgram.Inputs["PC"].Width;
            iConstWidth = oProgram.Outputs["CONST"].Width;
            iIRWidth = oProgram.Outputs["IR"].Width;

            ContainerBlock.CreateRegister("A", 32, true);
            ContainerBlock.CreateRegister("B", 32, true);
            ContainerBlock.CreateRegister("C", 32, true);
            ContainerBlock.CreateRegister("PC", iPCWidth, true);
            ContainerBlock.CreateRegister("SR", 5, true);
            ContainerBlock.CreateRegister("DR", 32, true);
            ContainerBlock.CreateRegister("QT", 6, true);
            ContainerBlock.CreateRegister("QI", 32, true);
            ContainerBlock.CreateRegister("QO", 32, true);
            ContainerBlock.CreateRegister("QA", 24, true);
            ContainerBlock.CreateRegister("QS", 1, true);
            ContainerBlock.CreateRegister("SP", 6, true);
            ContainerBlock.CreateRegister("RR", 6, true);
            ContainerBlock.CreateRegister("MC", 7, true);
            ContainerBlock.CreateRegister("ME", 1, true);

            ContainerBlock.CreateRegister("NA", 7, true);
            ContainerBlock.CreateRegister("NC", 14, true);
            ContainerBlock.CreateRegister("NT", 14, true);
            ContainerBlock.CreateRegister("NL", 8, true);

            ContainerBlock.CreateRAM("STACK", 32, 60,true);// should be bigger to be safe
            ContainerBlock.CreateRAM("NEURONS", 36 , 102, true);
            
            ContainerBlock.CreateALU("PC_INC",ALUType.Inc,iPCWidth);
            ContainerBlock.CreateALU("SP_INC",ALUType.Inc,6);
            ContainerBlock.CreateALU("SP_DEC", ALUType.Dec, 6);
            ContainerBlock.CreateALU("RR_INC", ALUType.Inc, 6);

            ContainerBlock.CreateALU("ADD", ALUType.Add, 32);
            ContainerBlock.CreateALU("SUB", ALUType.Subtract, 32);
            ContainerBlock.CreateALU("AND", ALUType.AndMask, 32);
            ContainerBlock.CreateALU("OR", ALUType.OrMask, 32);
            ContainerBlock.CreateConstant("ZERO", 0, 32);
            
            ContainerBlock.CreateResize("PAD_QT", 6, 32);
            ContainerBlock.Join("QT", "OUT", "PAD_QT", "IN");

            ContainerBlock.CreateResize("QA_OUT", 24, 32);
            ContainerBlock.Join("QA", "OUT", "QA_OUT", "IN");

            ContainerBlock.CreateLogicBlock("EQ", "IN1<32> = IN2<32>");
            ContainerBlock.CreateLogicBlock("GT", "IN1<32> > IN2<32>");
            ContainerBlock.CreateLogicBlock("REQ", "IN1<6> = IN2<6>");

            ContainerBlock.CreateALU("LSR8", ALUType.ShiftRightLogical, 32, 8);
            //ContainerBlock.CreateALU("LSR14", ALUType.ShiftRightLogical, 32, 14);
            ContainerBlock.CreateALU("LSR17", ALUType.ShiftRightLogical, 32, 17);
            ContainerBlock.CreateALU("LSL8", ALUType.ShiftLeftLogical, 32, 8);
            ContainerBlock.CreateALU("LSL14", ALUType.ShiftLeftLogical, 32, 14);
            //ContainerBlock.CreateALU("LSL17", ALUType.ShiftLeftLogical, 32, 17);
            ContainerBlock.CreateALU("LSR20", ALUType.ShiftRightLogical, 32, 20);
            //ContainerBlock.CreateALU("LSL20", ALUType.ShiftLeftLogical, 32, 20);


            ContainerBlock.CreateCombine("SR_IN",1,1,1);
            ContainerBlock.CreateBreakout("SR_OUT", 1,1,1);
            ContainerBlock.Join("SR_IN", "OUT", "SR", "IN");
            ContainerBlock.Join("SR","OUT","SR_OUT", "IN");
            ContainerBlock.Join("EQ", "OUT", "SR_IN", "IN1");
            ContainerBlock.Join("GT", "OUT", "SR_IN", "IN2");
            ContainerBlock.Join("REQ", "OUT", "SR_IN", "IN3");
            ContainerBlock.CreateStatusOutput("EQ", "SR_OUT", "OUT1");
            ContainerBlock.CreateStatusOutput("GT", "SR_OUT", "OUT2");
            ContainerBlock.CreateStatusOutput("REQ", "SR_OUT", "OUT3");

            if (iConstWidth < 32)
            {
                ContainerBlock.CreateCombine("C_IN", iConstWidth, 32 - iConstWidth);
                ContainerBlock.Join("PROG", "CONST", "C_IN", "IN1");
                ContainerBlock.CreateConstant("PAD_C", 0, 32 - iConstWidth);
                ContainerBlock.Join("PAD_C", "OUT", "C_IN", "IN2");
                ContainerBlock.Join("C_IN", "OUT", "C", "IN");
            }
            else
            {
                ContainerBlock.Join("PROG", "CONST", "C", "IN");
            }

            ContainerBlock.Join("PC", "OUT", "PC_INC", "IN1");
            ContainerBlock.Join("PROG", "IR", "CORE", "IR");
            ContainerBlock.Join("PC", "OUT", "PROG", "PC");

            ContainerBlock.CreateCombine("MEM_OUT", 32, 24, 6, 1,1);
            ContainerBlock.Join("DR", "OUT", "MEM_OUT", "IN1");
            ContainerBlock.Join("MEM_OUT", "OUT", "MEMQO", "IN");
            ContainerBlock.Join("RR", "OUT", "MEM_OUT", "IN3");
            ContainerBlock.Join("ZERO_BIT", "OUT", "MEM_OUT", "IN4");
            
            ContainerBlock.CreateBreakout("MEM_READ", 32, 2, 6, 2);
            //ContainerBlock.Join("MEM_READ", "OUT1", "DR", "IN");
            ContainerBlock.Join("MEMQI", "OUT", "MEM_READ", "IN");

            ContainerBlock.Join("RR", "OUT", "RR_INC", "IN1");
            ContainerBlock.Join("RR_INC", "OUT", "RR", "IN");
            ContainerBlock.Join("RR", "OUT", "REQ", "IN1");
            ContainerBlock.Join("MEM_READ", "OUT3", "REQ", "IN2");

            ContainerBlock.CreateCombine("E_OUT",32,2,6,1,1);
            ContainerBlock.Join("E_OUT","OUT","EQO","IN");
            ContainerBlock.Join("QO","OUT","E_OUT","IN1");
            ContainerBlock.Join("ZERO","OUT","E_OUT","IN2");
            ContainerBlock.Join("QT","OUT","E_OUT","IN3");
            ContainerBlock.Join("ZERO_BIT","OUT","E_OUT","IN4");

            ContainerBlock.CreateBreakout("E_IN", 32, 24, 6, 1, 1);
            ContainerBlock.Join("EQI", "OUT", "E_IN", "IN");
            ContainerBlock.Join("E_IN", "OUT1", "QI","IN");
            ContainerBlock.Join("E_IN", "OUT2", "QA","IN");
            ContainerBlock.Join("E_IN", "OUT3", "QT","IN");
            ContainerBlock.Join("E_IN", "OUT5", "QS","IN");

            ContainerBlock.Join("SP", "OUT", "STACK", "ADDRESS");
            ContainerBlock.Join("SP", "OUT", "SP_INC", "IN1");
            ContainerBlock.Join("SP", "OUT", "SP_DEC", "IN1");

            ContainerBlock.CreateALU("MC_INC", ALUType.Inc, 7);
            ContainerBlock.CreateALU("MC_TIMEOUT_GT", ALUType.CompareGreater, 7);
            ContainerBlock.CreateALU("MC_RETRY_GT", ALUType.CompareGreater, 7);
            ContainerBlock.CreateConstant("MC_TIMEOUT", 120, 7);
            ContainerBlock.CreateConstant("MC_RETRY", 60, 7);
            ContainerBlock.CreateConstant("MC_ZERO", 0, 7);

            ContainerBlock.CreateResize("MC_OUT", 7, 32);
            ContainerBlock.Join("MC","OUT","MC_OUT", "IN");

            ContainerBlock.Join("MC", "OUT", "MC_INC", "IN1");
            ContainerBlock.Join("MC_TIMEOUT", "OUT", "MC_TIMEOUT_GT", "IN2");
            ContainerBlock.Join("MC_RETRY", "OUT", "MC_RETRY_GT", "IN2");
            ContainerBlock.Join("MC", "OUT", "MC_TIMEOUT_GT", "IN1");
            ContainerBlock.Join("MC", "OUT", "MC_RETRY_GT", "IN1");

            ContainerBlock.CreateStatusOutput("MEM_TIMEOUT", "MC_TIMEOUT_GT", "OUT");
            ContainerBlock.CreateStatusOutput("MEM_RETRY", "MC_RETRY_GT", "OUT");
            ContainerBlock.CreateStatusOutput("MEM_ERROR", "ME", "OUT");


            ContainerBlock.CreateBreakout("NEURONS_OUT", 8, 14, 14);
            ContainerBlock.Join("NEURONS_OUT", "OUT1", "NL", "IN");
            ContainerBlock.Join("NEURONS_OUT", "OUT2", "NT", "IN");
            ContainerBlock.Join("NEURONS_OUT", "OUT3", "NC", "IN");
            ContainerBlock.CreateCombine("NEURONS_IN", 8, 14, 14);
            ContainerBlock.Join("NL", "OUT", "NEURONS_IN", "IN1");
            ContainerBlock.Join("NT", "OUT", "NEURONS_IN", "IN2");
            ContainerBlock.Join("NC", "OUT", "NEURONS_IN", "IN3");

            ContainerBlock.Join("NEURONS", "DATA_OUT", "NEURONS_OUT", "IN");
            ContainerBlock.Join("NEURONS_IN","OUT","NEURONS","DATA_IN");
            ContainerBlock.Join("NA", "OUT", "NEURONS", "ADDRESS");

            ContainerBlock.CreateResize("NA_32", 7, 32);
            ContainerBlock.CreateResize("NL_32", 8, 32);
            ContainerBlock.CreateResize("NT_32", 14, 32);
            ContainerBlock.CreateResize("NC_32", 14, 32);
            ContainerBlock.Join("NC", "OUT", "NC_32", "IN");
            ContainerBlock.Join("NL", "OUT", "NL_32", "IN");
            ContainerBlock.Join("NT", "OUT", "NT_32", "IN");
            ContainerBlock.Join("NA", "OUT", "NA_32", "IN");

            //ContainerBlock.CreateBreakout("A_TO_ROM", iIRWidth, iPCWidth, 32 - iIRWidth - iPCWidth);
            //ContainerBlock.Join("A", "OUT", "A_TO_ROM", "IN");

            //ContainerBlock.CreateCombine("PROG_WRITE_DATA", 32, iIRWidth);
            //ContainerBlock.Join("B", "OUT", "PROG_WRITE_DATA", "IN1");
            //ContainerBlock.Join("A_TO_ROM", "OUT1", "PROG_WRITE_DATA", "IN2");

            //ContainerBlock.Join("A_TO_ROM", "OUT2", "PROG", "ADDRESS");
            //ContainerBlock.Join("PROG_WRITE_DATA", "OUT", "PROG", "WRITE_DATA");


            //NOP
            ControlState oControl = ContainerBlock.CreateControlState("NOP");

            //PC_INC
            oControl = ContainerBlock.CreateControlState("PC_INC");
            oControl.Join("PC_INC", "OUT", "PC", "IN");
            oControl.Activate("PC", "LATCH");
            oControl.Activate("C", "LATCH");

            //PC_JUMP
            oControl = ContainerBlock.CreateControlState("PC_JUMP");
            oControl.Join("C", "OUT", "PC", "IN");
            oControl.Activate("PC", "LATCH");

            //COMP_QT_C
            oControl = ContainerBlock.CreateControlState("COMP_QT_C");
            Compare(oControl, "PAD_QT", "OUT", "C", "OUT");
         
            //LOAD_instructions
            LoadInstruction("A", "B");
            LoadInstruction("B", "A");
            LoadInstruction("QO", "A");
            LoadInstruction("A", "QI");
            LoadInstruction("QO", "B");
            LoadInstruction("B", "QI");
            LoadInstruction("DR", "A");
            LoadInstruction("A", "DR");
            LoadInstruction("DR", "B");
            LoadInstruction("B", "DR");
            LoadInstruction("QO", "QI");
            LoadInstruction("QT", "A");
            LoadInstruction("QT", "B");
                
            LoadConstInstruction("A");
            LoadConstInstruction("B");
            LoadConstInstruction("DR");

            //COMP_instructions
            CompareInstruction("A");
            CompareInstruction("B");
            CompareInstruction("DR");
            oControl = ContainerBlock.CreateControlState("COMP_MC_C");
            Compare(oControl, "MC_OUT", "OUT", "C", "OUT");

            oControl = ContainerBlock.CreateControlState("COMP_A_B");
            Compare(oControl, "A", "OUT", "B", "OUT");


            CompareInstruction("MC_OUT");

            //PUSH_PULL_instructions
            PushPullInstruction("A");
            PushPullInstruction("B");
            PushPullInstruction("DR");
            PushPullInstruction("PC");
            PushPullInstruction("SR");
            PushPullInstruction("QI");
            PushPullInstruction("QO");
            PushPullInstruction("QT");
            PushPullInstructionResized("NA");
            PushPullInstructionResized("NC");
            PushPullInstructionResized("NL");
            PushPullInstructionResized("NT");

            //INC_SP,DEC_SP
            oControl = ContainerBlock.CreateControlState("SP_DEC");
            oControl.Join("SP_DEC", "OUT", "SP","IN");
            oControl.Activate("SP", "LATCH");
            oControl = ContainerBlock.CreateControlState("SP_INC");
            oControl.Join("SP_INC", "OUT", "SP", "IN");
            oControl.Activate("SP", "LATCH");

            //ALU_instructions
            ALUInstruction("A", "AND", "C", "OUT");
            ALUInstruction("B", "AND", "C", "OUT");
            ALUInstruction("A", "OR", "C", "OUT");
            ALUInstruction("B", "OR", "C", "OUT");
            ALUInstruction("A", "ADD", "C", "OUT");
            ALUInstruction("B", "ADD", "C", "OUT");
            ALUInstruction("A", "SUB", "C", "OUT");
            //ALUInstruction("B", "SUB", "C", "OUT");
            ALUInstruction("A", "AND", "B", "OUT");
            ALUInstruction("A", "OR", "B", "OUT");
            ALUInstruction("A", "ADD", "B", "OUT");
            ALUInstruction("A", "SUB", "B", "OUT");

            ShiftInstruction("B", "8");
            ShiftInstruction("B", "14");
            ShiftInstruction("A", "17");
            ShiftInstruction("A", "20");

            //READ_instructions
            //MEM_READ
            oControl = ContainerBlock.CreateControlState("MEM_CLEAR");
            oControl.Activate("MEMQI", "READ");

            //LOAD_DR_MEM
            oControl = ContainerBlock.CreateControlState("LOAD_DR_MEMQI");
            oControl.Join("MEM_READ", "OUT1", "DR", "IN");
            oControl.Activate("DR", "LATCH");
            //Compare(oControl, "DR", "OUT", "ZERO", "OUT");

            //WRITE_instruction
            MemReq("A", true);
            MemReq("B", true);
            MemReq("A", false);
            MemReq("B", false);  
          
            //EQI
            EBusReq(true);
            EBusReq(false);

            //EQO
            //EQI_READ
            oControl = ContainerBlock.CreateControlState("EQI_READ");
            oControl.Activate("QI", "LATCH");
            oControl.Activate("QT", "LATCH");
            oControl.Activate("QS", "LATCH");
            oControl.Activate("QA", "LATCH");
            oControl.Activate("EQI", "READ");

            //LOAD_A_QA
            oControl = ContainerBlock.CreateControlState("LOAD_A_QA");
            oControl.Join("QA_OUT", "OUT", "A", "IN");
            oControl.Activate("A", "LATCH");
            //Compare(oControl, "QA_OUT", "OUT", "ZERO", "OUT");

            //LOAD_A_QB
            //oControl = ContainerBlock.CreateControlState("LOAD_B_QA");
            //oControl.Join("QA_OUT", "OUT", "B", "IN");
            //oControl.Activate("B", "LATCH");
            //Compare(oControl, "QA_OUT", "OUT", "ZERO", "OUT");

            //MEM_RESET
            oControl = ContainerBlock.CreateControlState("MEM_RESET");
            oControl.Join("MC_ZERO", "OUT", "MC", "IN");
            oControl.Activate("MC", "LATCH");
            oControl.Join("ZERO_BIT", "OUT", "ME", "IN");
            oControl.Activate("ME", "LATCH");
            oControl.Activate("RR", "LATCH");

            //MEM_ERROR
            oControl = ContainerBlock.CreateControlState("MEM_ERROR");
            oControl.Activate("ME", "LATCH");
            oControl.Join("ONE_BIT", "OUT", "ME", "IN");

            //MC_INC
            oControl = ContainerBlock.CreateControlState("MC_INC");
            oControl.Join("MC_INC", "OUT", "MC", "IN");
            oControl.Activate("MC", "LATCH");
            
            //Read_NEURON
            oControl = ContainerBlock.CreateControlState("READ_NEURON");
            oControl.Activate("NC", "LATCH");
            oControl.Activate("NT", "LATCH");
            oControl.Activate("NL", "LATCH");

            //write_NEURON
            oControl = ContainerBlock.CreateControlState("WRITE_NEURON");
            oControl.Activate("NEURONS", "WRITE");


            //WRITE_PROG_RAM
            //oControl = ContainerBlock.CreateControlState("WRITE_PROG_RAM");
            //oControl.Activate("PROG", "WRITE");
        }

        /*private void Compare(ControlState poControl, string psBlockA, string psInputA, string psBlockB, string psInputB)
        {
            Compare(poControl, psBlockA, psInputA, psBlockB, psInputB,false);
        }*/

        private void Compare(ControlState poControl, string psBlockA, string psInputA, string psBlockB, string psInputB)
        {
            poControl.Join(psBlockA, psInputA, "EQ", "IN1");
            poControl.Join(psBlockB, psInputB, "EQ", "IN2");
            poControl.Join(psBlockA, psInputA, "GT", "IN1");
            poControl.Join(psBlockB, psInputB, "GT", "IN2");         
            poControl.Activate("SR", "LATCH");
        }

        private void ShiftInstruction(string psReg, string psWidth)
        {
            if (ContainerBlock.Blocks.ContainsKey("LSL" + psWidth))
            {
                string sCommand = "LSL" + psWidth + "_" + psReg;
                ControlState oControl = ContainerBlock.CreateControlState(sCommand);
                oControl.Join(psReg, "OUT", "LSL" + psWidth, "IN1");
                oControl.Activate(psReg, "LATCH");
                oControl.Join("LSL" + psWidth, "OUT", psReg, "IN");
                //Compare(oControl, "LSL" + psWidth, "OUT", "ZERO", "OUT");
            }

            if (ContainerBlock.Blocks.ContainsKey("LSR" + psWidth))
            {
                string sCommand = "LSR" + psWidth + "_" + psReg;
                ControlState oControl = ContainerBlock.CreateControlState(sCommand);
                oControl.Join(psReg, "OUT", "LSR" + psWidth, "IN1");
                oControl.Activate(psReg, "LATCH");
                oControl.Join("LSR" + psWidth, "OUT", psReg, "IN");
                //Compare(oControl, "LSR" + psWidth, "OUT", "ZERO", "OUT");
            }
        }

        private void LoadInstruction(string psRegDestination, string psRegSource)
        {
            string sCommand = "LOAD_" + psRegDestination + "_" + psRegSource;
            ControlState oControl = ContainerBlock.CreateControlState(sCommand);
            oControl.Join(psRegSource, "OUT", psRegDestination, "IN");
            oControl.Activate(psRegDestination, "LATCH");
            //Compare(oControl, psRegSource, "OUT", "ZERO", "OUT");
        }

        private void LoadConstInstruction(string psRegDestination)
        {
            string sCommand = "LOAD_" + psRegDestination + "_C";
            ControlState oControl = ContainerBlock.CreateControlState(sCommand);
            oControl.Join("C", "OUT", psRegDestination, "IN");
            oControl.Activate(psRegDestination, "LATCH");
            //Compare(oControl, "C", "OUT", "ZERO", "OUT");
        }

        private void CompareInstruction(string psReg)
        {
            string sCommand = "COMP_" + psReg + "_C";
            ControlState oControl = ContainerBlock.CreateControlState(sCommand);
            Compare(oControl, psReg, "OUT", "C", "OUT");
        }

        private void Push(ControlState poControl, string psBlock, string psOutput)
        {
            //poControl.Join("SP", "OUT", "SP_INC", "IN1");
            //poControl.Join("SP", "OUT", "STACK", "ADDRESS");
            //poControl.Join("SP_INC", "OUT", "SP", "IN");
            poControl.Activate("STACK", "WRITE");
            //poControl.Activate("SP", "LATCH");
            poControl.Join(psBlock, psOutput, "STACK", "DATA_IN");
        }

        private void Pull(ControlState poControl, string psBlock, string psInput)
        {
            //poControl.Join("SP", "OUT", "SP_DEC", "IN1");
            //poControl.Join("SP_DEC", "OUT", "STACK", "ADDRESS");
            //poControl.Join("SP_DEC", "OUT", "SP", "IN");
            poControl.Join("STACK", "DATA_OUT", psBlock, psInput);
            poControl.Activate(psBlock, "LATCH");
            //poControl.Activate("SP", "LATCH");
        }


        private void PushPullInstruction(string psReg)
        {
            string sCommand = "PUSH_" + psReg;
            ControlState oControl = ContainerBlock.CreateControlState(sCommand);
            Push(oControl, psReg, "OUT");
            sCommand = "PULL_" + psReg;
            oControl = ContainerBlock.CreateControlState(sCommand);
            Pull(oControl, psReg, "IN");
        }


        private void PushPullInstructionResized(string psReg)
        {
            string sCommand = "PUSH_" + psReg;
            ControlState oControl = ContainerBlock.CreateControlState(sCommand);
            Push(oControl, psReg + "_32", "OUT");
            sCommand = "PULL_" + psReg;
            oControl = ContainerBlock.CreateControlState(sCommand);
            Pull(oControl, psReg, "IN");
        }


        private void ALUInstruction(string psReg, string psALU, string psBlockB, string psOutputB)
        {
            string sCommand = psALU + "_" + psReg + "_" + psBlockB;
            if (psBlockB == "PROG")
                sCommand = psALU + "_" + psReg + "_" + psOutputB;
            ControlState oControl = ContainerBlock.CreateControlState(sCommand);
            oControl.Join(psReg, "OUT", psALU, "IN1");
            oControl.Join(psBlockB, psOutputB, psALU, "IN2");
            oControl.Join(psALU, "OUT", psReg, "IN");
            oControl.Activate(psReg, "LATCH");
            Compare(oControl, psALU, "OUT", "ZERO", "OUT");
        }

        private void MemReq(string Addr, bool pbWrite)
        {
            string sCommand = "MEM_POST_READ_";
            if (pbWrite)
                sCommand = "MEM_POST_WRITE_";
                
            sCommand+= Addr;
            
            ControlState oControl = ContainerBlock.CreateControlState(sCommand);
            oControl.Join(Addr, "OUT", "ADD", "IN1");
            oControl.Join("C", "OUT", "ADD", "IN2");
            oControl.Join("ADD", "OUT", "MEM_OUT", "IN2");
            if (pbWrite)
                oControl.Join("ONE_BIT", "OUT", "MEM_OUT", "IN5");
            else
                oControl.Join("ZERO_BIT", "OUT", "MEM_OUT", "IN5");

            oControl.Activate("MEMQO", "LATCH");
        }

        private void EBusReq(bool pbWrite)
        {
            string sCommand = "EQI_POST_READ";
            if (pbWrite)
                sCommand = "EQI_POST_WRITE";
                
            ControlState oControl = ContainerBlock.CreateControlState(sCommand);
            if (pbWrite)
                oControl.Join("ZERO_BIT", "OUT", "E_OUT", "IN5");
            else
                oControl.Join("ONE_BIT", "OUT", "E_OUT", "IN5");

            oControl.Activate("EQO", "LATCH");
        }

        private void ReadQ(ControlState poControl, string psQ, string psDataReg)
        {
            poControl.Join(psQ, "OUT", psDataReg, "IN");
            poControl.Activate(psDataReg, "LATCH");
            poControl.Activate(psQ, "READ");
        }


        /*private void MemRead()
        {
            ControlState oControl = ContainerBlock.CreateControlState("MEM_READ");
            oControl.Activate("DR", "LATCH");
            oControl.Activate("MEMQI", "READ");
            Compare(oControl, "DR_IN", "OUT1", "ZERO", "OUT");     
        }

        private void MemClear()
        {
            ControlState oControl = ContainerBlock.CreateControlState("MEM_CLEAR");
            oControl.Activate("MEMQI", "READ");
            oControl.Activate("RR", "LATCH");
            Compare(oControl, "DR", "OUT", "ZERO", "OUT");     
        }*/

        public void AddSignalViews()
        {
            SignalView oSignalView = ContainerBlock.AddSignalView("A", "OUT",SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            oSignalView = ContainerBlock.AddSignalView("B", "OUT",SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            oSignalView = ContainerBlock.AddSignalView("DR", "OUT", SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            oSignalView = ContainerBlock.AddSignalView("SR", "OUT");
            oSignalView = ContainerBlock.AddSignalView("C", "OUT", SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            oSignalView = ContainerBlock.AddSignalView("PROG", "IR", SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            oSignalView = ContainerBlock.AddSignalView("PC", "OUT", SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            //oSignalView = ContainerBlock.AddSignalView("PAD_QT", "OUT", SignalFormat.Unsigned);
            //oSignalView.SignalFormat = SignalFormat.Unsigned;

            //oSignalView = ContainerBlock.AddSignalView("EQ", "IN1", SignalFormat.Unsigned);
            //oSignalView.Hidden = true;
            //oSignalView = ContainerBlock.AddSignalView("EQ", "IN2", SignalFormat.Unsigned);
            //oSignalView.Hidden = true;
            //oSignalView = ContainerBlock.AddSignalView("EQ", "OUT");
            //oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("QT", "OUT",SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            //oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("QI", "OUT",SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            //oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("QO", "OUT",SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            //oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("QA", "OUT",SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            //oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("QS", "OUT");
            oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("SP", "OUT",SignalFormat.Unsigned);
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            //oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("RR", "OUT",SignalFormat.Unsigned);
            //oSignalView.Hidden = true;
            //oSignalView = ContainerBlock.AddSignalView("STACK", "DATA_IN",SignalFormat.Unsigned);
            //oSignalView.SignalFormat = SignalFormat.Unsigned;
            //oSignalView.Hidden = true;
            //oSignalView = ContainerBlock.AddSignalView("STACK", "DATA_OUT", SignalFormat.Unsigned);
            //oSignalView.SignalFormat = SignalFormat.Unsigned;
            //oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("MEMQI", "OUT");
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("MEMQI", "READY");
            oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("EQI", "OUT");
            oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("EQI", "READY");
            oSignalView.SignalFormat = SignalFormat.Unsigned;
            oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("MEMQO", "STALL");
            oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("EQO", "STALL");
            oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("MC", "OUT");
            oSignalView.Hidden = true;
            oSignalView = ContainerBlock.AddSignalView("ME", "OUT");
            oSignalView.Hidden = false; 
            //oSignalView = ContainerBlock.AddSignalView("MC_TIMEOUT_GT", "OUT");
            //oSignalView = ContainerBlock.AddSignalView("MC_RETRY_GT", "OUT");



            oMicroCore.AddSignalViews();
            oProgram.AddSignalViews();
        }

        public void SignalDisplay(HardwareScript poScript, int piClockTime)
        {
            ContainerBlock.SignalDisplay(poScript, piClockTime);
            oMicroCore.SignalDisplay(poScript, piClockTime);
            oProgram.SignalDisplay(poScript,piClockTime);
        }
        
        /*public bool WriteRAMToFPGA()
        {
            return oProgram.WriteRAMToFPGA();
        }*/

        public string GetProgramText()
        {
            return oProgram.GetProgramText();
        }

        public Dictionary<int, int> GetProgramAddressToLine()
        {
            return oProgram.GetProgramAddressToLine();
        }

        /*public bool StartRAMOnFPGA()
        {
            return oProgram.StartRAMOnFPGA();
        }*/

        public void LoadRAMProgram()
        {
            oProgram.LoadRAMProgram();
        }
    }
}
